﻿using System;
using System.Collections.Generic;
using System.Text;
using net.veekee.common;
using System.Text.RegularExpressions;
using System.Collections;
using System.Reflection;
using net.veekee.common.data;
using net.veekee.logprocessor.plugin.context;
using net.veekee.logprocessor.plugin.input;

namespace net.veekee.logprocessor.plugin.output
{
    public abstract class AWriter : IDisposable
    {
        protected String FileName = "";
        public String Filename
        {
            get
            {
                return this.FileName;
            }
        }

        protected FieldManager Fields = null;
        protected ShortFileContext context;

        public AWriter()
        {
            this.Fields = new FieldManager();
        }

        public virtual void SetContext(ShortFileContext c)
        {
            this.context = c;
        }

        public abstract bool Load(String filename);

        protected virtual void AddLine(params Object[] items)
        {
            this.AddLine(items.GetEnumerator());
        }

        protected abstract void AddLine(IEnumerator items);

        protected virtual void WriteHeader()
        {
            if (this.context.Header == null)
            {
                Log.GetInstance().Info("No output fields were set... void output will be generated");
                return;
            }
            this.Fields.Load(this.context.Header);
            bool fileExists = System.IO.File.Exists(this.FileName);
            bool fileEmpty = (new System.IO.FileInfo(this.FileName).Length == 0);
            if (!this.context.Append || !fileExists || fileEmpty)
                this.AddLine(this.Fields.Keys.GetEnumerator());
        }

        public virtual void WriteEntry(AnEntry entry)
        {
            if (entry == null)
                return;
            List<Object> values = new List<Object>();
            foreach (String field in this.Fields.Keys)
            {
                String targetedVar = this.Fields.Get(field);
                Object val = null;
                try {
                    if (targetedVar.Length > 0)
                    {
                        if (targetedVar.Contains("["))
                        {
                            String fieldVal = targetedVar.Substring(0, targetedVar.IndexOf("["));
                            String fieldIdxS = targetedVar.Substring(targetedVar.IndexOf("[") + 1, targetedVar.IndexOf("]") - targetedVar.IndexOf("[") - 1);
                            int fieldIdx = 0;
                            Int32.TryParse(fieldIdxS, out fieldIdx);
                            Object a = entry.Fields.Get<Object>(fieldVal);
                            if (a != null)
                            {
                                Type t = a.GetType();
                                int count = -1;
                                MethodInfo mi = t.GetMethod("get_Count", new Type[] { });
                                if (mi != null)
                                    count = (int)mi.Invoke(a, new Object[] { });
                                if (fieldIdx < count)
                                {
                                    mi = t.GetMethod("get_Item", new Type[] { typeof(Int32) });
                                    if (mi != null)
                                        val = mi.Invoke(a, new Object[] { fieldIdx });
                                }
                            }
                        }
                        else
                        {
                            val = entry.Fields.Get<Object>(targetedVar);
                        }
                    }
                } catch {
                }
                if (val == null)
                    val = "";
                values.Add(val);
            }
#if DEBUG
            StringBuilder sb = new StringBuilder();
            IEnumerator e = values.GetEnumerator();
            while (e.MoveNext())
            {
                sb.Append(e.Current.ToString() + ";");
            }
            Log.GetInstance().Trace(sb.ToString());
#endif
            this.AddLine(values.GetEnumerator());
        }

        public abstract void WriteFooter();

        public abstract void Dispose();
    }
}
